package com.dc.base.utils;

import android.content.Context;
import android.util.Log;

import com.dc.base.BaseApp;

import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;

/**
 * 日志存储本地工具类
 *
 * @author 冰柠檬dc
 */
public class LogUtil {

    /**
     * 日志文件总数
     */
    private static final int LOG_FILE_TOTAL = 10;
    /**
     * 单日志文件大小上限 MB
     */
    private static final long LOG_SIZE_MAX = 10;

    /**
     * 文件名格式
     */
    private static final SimpleDateFormat FILE_NAME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss-SSS");

    private static final String LOG_DIR = "log";

    private static final Object LOCK = new Object();


    public static void d(String tag, String msg) {
        synchronized (LOCK) {
            Log.d(tag, msg);
            printLog("DEBUG", tag, msg);
        }
    }

    public static void i(String tag, String msg) {
        synchronized (LOCK) {
            Log.i(tag, msg);
            printLog("INFO ", tag, msg);
        }
    }

    public static void w(String tag, String msg) {
        synchronized (LOCK) {
            Log.i(tag, msg);
            printLog("WARN ", tag, msg);
        }
    }

    public static void e(String tag, String msg) {
        synchronized (LOCK) {
            Log.i(tag, msg);
            printLog("ERROR", tag, msg);
        }
    }

    private static void printLog(String level, String TAG, String msg) {
        long size = FileUtil.isSDCardEnable() ? FileUtil.getAvailableExternalMemorySize(BaseApp.getContext()) : FileUtil.getAvailableInternalMemorySize();
        if (size < LOG_SIZE_MAX * LOG_FILE_TOTAL) {
            Log.e("LogUtil", "printLog, memory size is too low");
            return;
        }
        ThreadUtil.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    FileWriter fileWriter = new FileWriter(getFile(), true);
                    fileWriter.write(formatLog(level, TAG, msg));
                    fileWriter.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 格式化日志
     *
     * @param level String
     * @param tag   String
     * @param msg   String
     * @return String
     */
    private static String formatLog(String level, String tag, String msg) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        StringBuilder builder = new StringBuilder();
        builder.append(dateFormat.format(new Date(System.currentTimeMillis()))).append(" ");
        builder.append("[").append(level).append("] ");
        builder.append("[").append(tag).append("] ");
        builder.append(msg);
        builder.append("\n");
        return builder.toString();
    }

    /**
     * @return
     */
    private static File getFile() {
        String filePrintDir = getFilePrintDir();
        // 确认文件夹是否存在
        File fileDir = new File(filePrintDir);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        // 获取文件夹下的日志文件
        File[] fileList = fileDir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".log");
            }
        });
        int fileCount = fileList == null ? 0 : fileList.length;

        // 没有日志文件时，直接创建新文件
        if (fileCount == 0) {
            return createLogFile();
        }

        // 只有一个日志文件时，确认是否需要创建新日志文件
        if (fileCount == 1) {
            return isCreateLogFile(fileList, false);
        }

        // 对日志排序，排序结果为升序
        Arrays.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File file1, File file2) {
                String file1Name = file1.getName().split(".log")[0];
                String file2Name = file2.getName().split(".log")[0];
                try {
                    Date dateFile1 = FILE_NAME_FORMAT.parse(file1Name);
                    Date dateFile2 = FILE_NAME_FORMAT.parse(file2Name);
                    if (dateFile1 != null && dateFile2 != null) {
                        return dateFile1.getTime() < dateFile2.getTime() ? -1 : 1;
                    } else {
                        return 0;
                    }
                } catch (Exception e) {
                    Log.i("LogUtil", "file1Name:" + file1Name + ",   file2Name:" + file2Name);
                }
                return 0;
            }
        });
        File lastFile = fileList[fileCount - 1];
        // 日志文件未达到最大控制个数
        if (fileCount < LOG_FILE_TOTAL) {
            return isCreateLogFile(fileList, false);
        }
        return isCreateLogFile(fileList, true);
    }


    /**
     * 确认是否需要创建新日志文件
     *
     * @param fileList    File[]
     * @param isFileTotal 已有日志文件个数是否达到日志文件总数
     * @return File
     */
    private static File isCreateLogFile(File[] fileList, boolean isFileTotal) {
        File lastFile = fileList[fileList.length - 1];
        // 超过日志文件大小上限，需要创建新日志文件
        if (lastFile.length() >= LOG_SIZE_MAX) {
            if (isFileTotal) {
                // 如果达到文件最大个数，删除时间最早的一个文件
                fileList[0].delete();
            }
            return createLogFile();
        }
        return lastFile;
    }


    /**
     * 创建一个新的日志文件
     *
     * @return File
     */
    private static File createLogFile() {
        String filePrintDir = getFilePrintDir();
        return new File(filePrintDir + FILE_NAME_FORMAT.format(new Date(System.currentTimeMillis())) + ".log");
    }

    private static String getFilePrintDir() {
        Context context = BaseApp.getContext();
        String dir;
        if (FileUtil.isSDCardEnable()) {
            dir = FileUtil.getExternalFilesDir(context).getAbsolutePath();
        } else {
            dir = FileUtil.getFilesDir(context).getAbsolutePath();
        }
        return dir + File.separator + LOG_DIR + File.separator;
    }
}
